package com.lau.conf;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@EnableAsync
@Configuration
public class ThreadPoolConfig implements AsyncConfigurer {


    /**
     * 核心线程数
     */
    @Value("${thread.system.threadCorePoolSize}")
    private String threadCorePoolSize;

    /**
     * 最大线程数
     */
    @Value("${thread.system.threadMaxPoolSize}")
    private String threadMaxPoolSize;

    /**
     * 阻塞任务队列
     */
    @Value("${thread.system.queueCapacity}")
    private String queueCapacity;

    /**
     * 部分线程空闲最大存活时间
     */
    @Value("${thread.system.keepAliveSeconds}")
    private String keepAliveSeconds;

    @Bean("asyncTaskExecutor")
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(Integer.parseInt(threadCorePoolSize));
        threadPoolTaskExecutor.setMaxPoolSize(Integer.parseInt(threadMaxPoolSize));
        threadPoolTaskExecutor.setAllowCoreThreadTimeOut(true);
        threadPoolTaskExecutor.setQueueCapacity(Integer.parseInt(queueCapacity));
        threadPoolTaskExecutor.setKeepAliveSeconds(Integer.parseInt(keepAliveSeconds));
        threadPoolTaskExecutor.setThreadNamePrefix("system-");
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 设置线程池关闭的时候等待所有任务都完成再继续销毁其他bean
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池任务的等待时间，如果超过这个时候还没有结束，就强制销毁，以确保应用最后关闭不会阻塞
//        threadPoolTaskExecutor.setAwaitTerminationSeconds(50);
        return threadPoolTaskExecutor;

    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            log.error("调用异步方法异常： \n" + method, ex);
        };
    }
}
